﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Diagnostics;

namespace FindPath
{
    class WSUtils
    {
        private static TcpClient _instance;
        private static System.Net.IPEndPoint hostAddress = null;
        private static byte[] getIpFromString(string ip) {
            byte[] result = new byte[4];
            string[] splitEle = ip.Split('.');
            int i = 0;
            foreach (string ele in splitEle) {
                result[i] = byte.Parse(ele);
                i++;
            }
            return result;

        }
        public static bool openSocket(string ip, int port)
        {
            //System.Net.IPAddress address = new System.Net.IPAddress
            try
            {
                _instance = new TcpClient(ip, port);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
            
        }
        public static void closeSocket(int id)
        {
            if (_instance != null)
            {
                _instance.Close();
            }
        }
        public static bool sendData(string data) {
            return sendFullData(packPacket(data));
        }
        public static bool sendFullData(string packet) {
            TcpClient client = getTCPClient();
            if (client.Connected)
            {
                int length = packet.Length / 2;
                byte[] asciiPacket =  new byte[length];
                for (int i = 0; i < length; i ++)
                {
                    asciiPacket[i] = (byte) (byte.Parse(packet.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber)^Constants.MASK_BYTE);
                }
                client.GetStream().Write(asciiPacket, 0, asciiPacket.Count());
                return true;
            }
            else
            {
                return false;
            }
        }
        public static TcpClient getTCPClient()
        {
            if (_instance == null)
            {
                if (hostAddress != null)
                {

                    _instance = new TcpClient(hostAddress);
                }
                else
                {
                   
                }
            }
            return _instance;
        }
        public static string encodeString(string input)
        {
            StringBuilder builder = new StringBuilder();
            byte[] data = System.Text.Encoding.ASCII.GetBytes(input);
            foreach (byte eachByte in data)
            {
                builder.Append(eachByte.ToString("X2"));
            }
            return builder.ToString();
        }
        public static string reverseString(string input)
        {
            if (input == null) return null;
            char[] charArray = input.ToCharArray();
            int len = input.Length - 1;

            for (int i = 0; i < len; i++, len--)
            {
                charArray[i] ^= charArray[len];
                charArray[len] ^= charArray[i];
                charArray[i] ^= charArray[len];
            }

            return new string(charArray);
        }
        public static string reverseByteString(string input)
        {
            if (input.Length % 2 != 0)
            {
                input = "0" + input;
            }
            StringBuilder builder = new StringBuilder("");
            if (input.Length < 2)
            {
                return input;
            }
            for (int i = input.Length - 1; i>=1; i-=2)
            {
                builder.Append(input.Substring(i - 1, 2));
            }
            return builder.ToString();
        }
        public static byte[] stringToBytes(string input)
        {
            if (input.Length % 2 != 0)
            {
                input = "0" + input;
            }
            byte[] result = new byte[input.Length / 2];
            for (int i = 0; i < input.Length; i++) {
                byte eachByte = byte.Parse(input.Substring(i*2, 2));
                result[i] = eachByte;
            }
            return result;
        }
        public static string encodeNumber(int input, int outDigit)
        {
            string result = "";
            result = reverseByteString(input.ToString("X" + outDigit*2));
            return result;
        }
        public static int decodeNumber(byte[] data, int start, int length)
        {
            int result = 0;
            for (int i = length - 1 ; i >= 0; i--)
            {
                result = result*256 + data[i + start];
            }
            return result;
        }
        public static int decodeNumber(string data, int outDigit)
        {
            int result = 0;
            result = int.Parse(reverseByteString(data), System.Globalization.NumberStyles.HexNumber);
            /*for (int i = 0; i < outDigit; i++)
            {
                int partEle = int.Parse(data.Substring(i*2, 2), System.Globalization.NumberStyles.HexNumber);
                result = result + (int)(partEle*Math.Pow(256, i)) ;
            }*/

            return result;
        }
        public static string decodeString(string data)
        {
            return System.Text.Encoding.ASCII.GetBytes(data).ToString();
        }
        public static string decodeString(byte[] data, int start, int length)
        {
            return System.Text.Encoding.ASCII.GetString(data, start, length);
        }
        public static string decodeUTFString(byte[] data, int start, int length)
        {
            return System.Text.Encoding.UTF8.GetString(data, start, length);
        }
        public static string printBytes(byte[] data, long length)
        {
            StringBuilder builder = new StringBuilder("");
            for (long i = 0; i < length; i++)
            {
                byte each = 0x00;
                if (i < data.Length)
                {
                    each = data[i];
                }
                
                builder.Append(each.ToString("X2") + " ");
                
            }
            return builder.ToString();

        }
        public static byte[] decodePacket(byte[] data, int dataLength)
        {
            byte[] packet = new byte[dataLength];
            for (int i = 0; i < dataLength; i++ )
            {
                byte eachByte = data[i];
                packet[i] = (byte)(eachByte ^ Constants.MASK_BYTE);
            }
            return packet;
        }
        
        public static string packPacket(string data)
        {

            string result = data.Replace(" ", "");
            int length = (result.Length / 2);
            result = Constants.PACKET_HEADER + encodeNumber(length, 2) + result;
            return result;
        }

        public static bool login(int userId, string password, string loginHeader, int version)
        {
            return WSUtils.sendData(CommandConstants.LOGIN_COMMAND + encodeNumber(userId, 4) + encodeString(loginHeader) +  encodeNumber(version, 2) + encodeString(password));
        }
    }

    
}
